/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pronostico;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Random;

/**
 *
 * @author Shadow
 */
public class Pronostico {

    private Calendar initDate;
    private Historico historico = Historico.getInstance();
    private double[] razonCalculadaDivTurno1 = new double[4];
    private double[] razonCalculadaDivTurno2 = new double[4];
    private double[] razonCalculadaDivTurno3 = new double[4];
    private double sumaRazonTurno1 = 0;
    private double sumaRazonTurno2 = 0;
    private double sumaRazonTurno3 = 0;
    private HashMap[] prioridadesDivTurno1 = new HashMap[4];
    private HashMap[] prioridadesDivTurno2 = new HashMap[4];
    private HashMap[] prioridadesDivTurno3 = new HashMap[4];

    public void calculaEstadisticas() {

        double[] razonDivTurno1 = new double[4];
        double[] razonDivTurno2 = new double[4];
        double[] razonDivTurno3 = new double[4];
        int[] nPaquetesTotDivTurno1 = new int[4];
        int[] nPaquetesTotDivTurno2 = new int[4];
        int[] nPaquetesTotDivTurno3 = new int[4];
        int[] prioridades = {1, 2, 4, 8, 24};
        for (int i = 0; i < 4; i++) {
            prioridadesDivTurno1[i] = new HashMap();
            prioridadesDivTurno2[i] = new HashMap();
            prioridadesDivTurno3[i] = new HashMap();
            razonDivTurno1[i] = 0;
            razonDivTurno2[i] = 0;
            razonDivTurno3[i] = 0;
            nPaquetesTotDivTurno1[i] = 0;
            nPaquetesTotDivTurno2[i] = 0;
            nPaquetesTotDivTurno3[i] = 0;
        }
        int nDias = historico.getDias().size();
        HashMap hashPrioridades1;
        HashMap hashPrioridades2;
        HashMap hashPrioridades3;


        for (int i = 0; i < nDias; i++) {
            Turno turno1 = historico.getDias().get(i).get(0);
            Turno turno2 = historico.getDias().get(i).get(1);
            Turno turno3 = historico.getDias().get(i).get(2);
            for (int j = 0; j < 4; j++) {
                razonDivTurno1[j] += (double) turno1.getDivisiones()[j].getRazonPaqTurno();
                razonDivTurno2[j] += (double) turno2.getDivisiones()[j].getRazonPaqTurno();
                razonDivTurno3[j] += (double) turno3.getDivisiones()[j].getRazonPaqTurno();
                //Prioridades
                hashPrioridades1 = turno1.getDivisiones()[j].getPrioridades();
                hashPrioridades2 = turno2.getDivisiones()[j].getPrioridades();
                hashPrioridades3 = turno3.getDivisiones()[j].getPrioridades();
                nPaquetesTotDivTurno1[j] += turno1.getDivisiones()[j].getnPaquetes();
                nPaquetesTotDivTurno2[j] += turno2.getDivisiones()[j].getnPaquetes();
                nPaquetesTotDivTurno3[j] += turno3.getDivisiones()[j].getnPaquetes();

                for (int k = 0; k < prioridades.length; k++) {
                    if (hashPrioridades1.containsKey(prioridades[k])) {
                        if (prioridadesDivTurno1[j].containsKey(prioridades[k])) {
                            prioridadesDivTurno1[j].put(prioridades[k], (int) prioridadesDivTurno1[j].get(prioridades[k]) + 1);
                        } else {
                            prioridadesDivTurno1[j].put(prioridades[k], 1);
                        }
                    }
                    if (hashPrioridades2.containsKey(prioridades[k])) {
                        if (prioridadesDivTurno2[j].containsKey(prioridades[k])) {
                            prioridadesDivTurno2[j].put(prioridades[k], (int) prioridadesDivTurno2[j].get(prioridades[k]) + 1);
                        } else {
                            prioridadesDivTurno2[j].put(prioridades[k], 1);
                        }
                    }
                    if (hashPrioridades3.containsKey(prioridades[k])) {
                        if (prioridadesDivTurno3[j].containsKey(prioridades[k])) {
                            prioridadesDivTurno3[j].put(prioridades[k], (int) prioridadesDivTurno3[j].get(prioridades[k]) + 1);
                        } else {
                            prioridadesDivTurno3[j].put(prioridades[k], 1);
                        }
                    }
                }
            }
        }
        double totalDivTurno1 = 0;
        double totalDivTurno2 = 0;
        double totalDivTurno3 = 0;

        for (int i = 0; i < 4; i++) {
            totalDivTurno1 += razonDivTurno1[i];
            totalDivTurno2 += razonDivTurno2[i];
            totalDivTurno3 += razonDivTurno3[i];
        }
        for (int i = 0; i < 4; i++) {
            razonDivTurno1[i] = razonDivTurno1[i] / totalDivTurno1;
            razonDivTurno2[i] = razonDivTurno2[i] / totalDivTurno2;
            razonDivTurno3[i] = razonDivTurno3[i] / totalDivTurno3;
            razonCalculadaDivTurno1[i] = razonDivTurno1[i];
            razonCalculadaDivTurno2[i] = razonDivTurno2[i];
            razonCalculadaDivTurno3[i] = razonDivTurno3[i];
            sumaRazonTurno1 += razonCalculadaDivTurno1[i];
            sumaRazonTurno2 += razonCalculadaDivTurno2[i];
            sumaRazonTurno3 += razonCalculadaDivTurno3[i];
        }

        //generar archivos

    }

    public static void main(String[] args) {
        Pronostico pronostico = new Pronostico();
        //Calendar diaInicio = Calendar.getInstance();
        //diaInicio.set(2012, 4, 17);
        //pronostico.hallaPronostico(diaInicio);
        //ArrayList<ArrayList<Turno>> días = Historico.getInstance().getDias();

        //int i = 0;
        generarArchivos();
    }

    public void hallaPronostico(Calendar diaInicio) {
        this.initDate = (Calendar) diaInicio.clone();
        while (true) {
            String dia = String.valueOf(diaInicio.get(Calendar.DATE));
            String mes = String.valueOf(diaInicio.get(Calendar.MONTH) + 1);
            String anho = String.valueOf(diaInicio.get(Calendar.YEAR));
            if (dia.length() == 1) {
                dia = '0' + dia;
            }
            if (mes.length() == 1) {
                mes = '0' + mes;
            }
            while (anho.length() > 4) {
                anho = '0' + anho;
            }
            if (!ManejaArchivos.leeDatos(dia, mes, anho)) {
                break;
            }
            diaInicio.add(Calendar.DAY_OF_MONTH, 1);
        }
        calculaEstadisticas();
        double razonT1 = razonCalculadaDivTurno1[0];
        ManejaArchivos.generaArchivos(this);
    }

    public static void generarArchivos() {
        float n1 = (float) 1.0555;
        float n2 = (float) 1.0995;
        float n3 = (float) 1.0755;

        String fecha, horaPedido;
        String nomArch = new String();
        int day, month, year;
        int cantTemp;
        int hora = 0;
        int minuto = 0;
        Calendar diaInicio = Calendar.getInstance();
        diaInicio.set(2013, 4, 20);
        Random randomGenerator = new Random();
        day = 300;
        int diafinal = 370; //370;

        for (; day <= diafinal; day++) {
            nomArch = nomArch.concat("dat");
            diaInicio.add(Calendar.DAY_OF_MONTH, 1);
            String dia = String.valueOf(diaInicio.get(Calendar.DATE));
            String mes = String.valueOf(diaInicio.get(Calendar.MONTH)+1);
            String anho = String.valueOf(diaInicio.get(Calendar.YEAR));
            if (dia.length() == 1) {
                dia = '0' + dia;
            }
            if (mes.length() == 1) {
                mes = '0' + mes;
            }
            while (anho.length() > 4) {
                anho = '0' + anho;
            }
            nomArch = "dat" + anho + mes + dia + ".txt";

            BufferedReader r = null;
            try {
                URL rutaca = Pronostico.class.getProtectionDomain().getCodeSource().getLocation();
                String ruta = rutaca.toString().substring(6, rutaca.toString().length()-47) + "web/WEB-INF/filesPronostico/";
                //String ruta = rutaca.toString().substring(6, rutaca.toString().length() - 26) + "web/WEB-INF/filesGenerados/";
                ruta = ruta.replaceAll("%20", " ");
                ruta = ruta + nomArch;
                File archivo = new File(ruta);
                if (archivo.exists()) {
                    archivo.delete();
                    //archivo.deleteOnExit();
                }
                archivo = new File(ruta);
                FileWriter escribir = new FileWriter(archivo, true);

                //System.out.println(dia + "/" + mes + "/" + anho);
                int cantPaqT1 = (int) (36 + Math.pow(day, n1) + (randomGenerator.nextDouble() * 10) + 1);
                int cantPaqT2 = (int) (60 + Math.pow(day, n2) + (randomGenerator.nextDouble() * 10) + 1);
                int cantPaqT3 = (int) (58 + Math.pow(day, n3) + (randomGenerator.nextDouble() * 10) + 1);
                generarPaquete(1, cantPaqT1-100, diaInicio, escribir);
                generarPaquete(2, cantPaqT2-100, diaInicio, escribir);
                generarPaquete(3, cantPaqT3-100, diaInicio, escribir);
               // System.out.println("###################################################");
                //System.out.println(cantPaqT1 + cantPaqT2 + cantPaqT3);
                escribir.close();
            } catch (Exception e) {
               // System.out.println(e.toString());
            }
        }
    }

    private static void generarPaquete(int turno, int CantMaxPaquete, Calendar diaInicio, FileWriter escribir) throws IOException {
        int idPedido = 177302;
        Random randomGenerator = new Random();
        int sumdiv = 1;
        String horabase = new String();
        int[] divisores = new int[4];
        int[] parte = new int[4];
        String tmphora = "00:00";
        int[] frecEntrega = new int[5];

        int partes;
        int nroReg;
        float delta, porcion;
        int asigna;
        int i, j;

        int posx, posy;
        int npaquete;
        int idcliente;
        int hlimite;
        int[] tlimite = {1, 2, 4, 8, 24};


        int tfrecEntrega = 0;
        int imax;

        switch (turno) {
            case 1:
                horabase.concat("00:00");
                //divisores={1,2,3,3};
                divisores[0] = 1;
                divisores[1] = 1;
                divisores[2] = 2;
                divisores[3] = 4;
                sumdiv = 8;
                break;
            case 2:
                horabase.concat("08:00");
                //divisores={3,4,5,6};
                divisores[0] = 4;
                divisores[1] = 6;
                divisores[2] = 9;
                divisores[3] = 12;
                sumdiv = 31;
                break;
            case 3:
                horabase.concat("16:00");
                //divisores={6,4,2,1};
                divisores[0] = 12;
                divisores[1] = 13;
                divisores[2] = 8;
                divisores[3] = 3;
                sumdiv = 36;
                break;
        }

        // define cuantos paquetes por tramo
        partes = 0;
        for (i = 0; i <= 2; i++) {
            parte[i] = CantMaxPaquete * divisores[i] / sumdiv;
            partes += parte[i];
        }
        parte[3] = CantMaxPaquete - partes;

        for (i = 0; i <= 3; i++) {
            //  para cada tramo, que son 4 tramos cada uno de 120 minutos = 2 horas.
            if (parte[i] < 3) {
                nroReg = 2;
                parte[i] = 4;
            } else {
                nroReg =  2 + parte[i] / 5 + (int)(randomGenerator.nextDouble() * ( parte[i] / 3));
            }

            //nroReg: número de pedidos que se generan en el turno-tramo (de 2 horas)  	  
            //   nroReg= 2 + (rand())%((int)round(parte[i]/2+0.5));  // o debe ser 1?
            if (nroReg < 120) // si es un número razonable ok, si son demasiados... debo ajustarlo
            {
                delta = Math.round(120.0 / nroReg * 100) / 100;
            } // delta es cada cuando se genera el pedido en el tiempo
            else {
                delta = 1;   //0.4;	
                nroReg = 120;  // 99
            }

            porcion = (parte[i] / nroReg);
            for (j = 0; j <= nroReg - 2; j++) {
                if (parte[i] < 3) {
                    asigna = 1;
                } else //     asigna = round( 1+ rand()%((int)(parte[i]/2)));
                {
                    asigna = (int) Math.round(1 + randomGenerator.nextDouble() * 1.4* ((int) (porcion)));
                }
                // patron: hh:mm,posx,posy,NroPaq,IdCliente,hlimite
                // arma los datos para grabar      
                tmphora = calchorapedido(turno, delta * j + 120 * i);
                //   printf("La horar pedido es %s \n", tmphora);
                //   getch();      
                posx = (int) (randomGenerator.nextDouble() * 0.7 * 150);
                posy = (int) (randomGenerator.nextDouble() * 0.7 * 100);

                // almacen.... X= 45
                //             Y= 30
                while ((posx % 45) == 0) {
                    posx++;
                }
                while ((posy % 30) == 0) {
                    posy++;
                }

                npaquete = asigna;
                idcliente = (int) (randomGenerator.nextDouble() * 400 + 1);

                // se fija el límite máximo de 24 hrs.
                hlimite = tlimite[4];

                if (tfrecEntrega == 0) {
                    switch (turno) {
                        case 1:
                            //entrega={1,2,5,8,4};
                            frecEntrega[0] = 1;
                            frecEntrega[1] = 2;
                            frecEntrega[2] = 5;
                            frecEntrega[3] = 8;
                            frecEntrega[4] = 4;
                            tfrecEntrega = 20;
                            break;
                        case 2:
                            //entrega={5,6,5,3,1};
                            frecEntrega[0] = 5;
                            frecEntrega[1] = 6;
                            frecEntrega[2] = 5;
                            frecEntrega[3] = 3;
                            frecEntrega[4] = 1;
                            tfrecEntrega = 20;
                            break;
                        case 3:
                            //entrega={5,5,5,3,2};
                            frecEntrega[0] = 5;
                            frecEntrega[1] = 5;
                            frecEntrega[2] = 5;
                            frecEntrega[3] = 3;
                            frecEntrega[4] = 2;
                            tfrecEntrega = 20;
                            break;
                    }

                }
                //	int itemmaximo(int numero[])        
                imax = itemmaximo(frecEntrega);
                hlimite = tlimite[imax];
                frecEntrega[imax]--;
                tfrecEntrega--;

                if (!((hlimite == 1) || (hlimite == 2) || (hlimite == 4) || (hlimite == 8) || (hlimite == 24))) {
                    hlimite = tlimite[(int) randomGenerator.nextDouble() * 5];
                }
                if ((hlimite == 1) || (hlimite == 2) || (hlimite == 4)) {  // pendiente negativo....      
                    posx = (int) (45 + (randomGenerator.nextDouble() * (10 * hlimite)));
                    posy = (int) (30 + (randomGenerator.nextDouble() * (10 * hlimite)));
                }
                while ((posx % 45) == 0) {
                    posx++;
                }
                while ((posy % 30) == 0) {
                    posy++;
                }
                asigna = (asigna > parte[i]?parte[i]:asigna);
                parte[i] -= asigna;
                String linea = tmphora + "," + posx + "," + posy + "," + npaquete + "," + idcliente + "," + hlimite + "\r\n";
                escribir.write(linea);
                if (parte[i] == 0) break;
            }
            if (parte[i] == 0) continue;
            tmphora = calchorapedido(turno, delta * (nroReg - 1) + 120 * i);

            if (parte[i] > 0) {
                asigna = parte[i];
            } else {
                asigna = 1;
            }

            posx = (int) (randomGenerator.nextDouble() * 150);
            posy = (int) (randomGenerator.nextDouble() * 100);

            while ((posx % 45) == 0) {
                posx++;
            }
            while ((posy % 30) == 0) {
                posy++;
            }

            npaquete = asigna;
            idcliente = (int) (randomGenerator.nextDouble() * 400 + 401);

            hlimite = 24;//tlimite[(int) randomGenerator.nextDouble() * 5];
            if (!((hlimite == 1) || (hlimite == 2) || (hlimite == 4) || (hlimite == 8) || (hlimite == 24))) {
                hlimite = tlimite[(int) randomGenerator.nextDouble() * 5];
            }
            if ((hlimite == 1) || (hlimite == 2) || (hlimite == 4)) {  // pendiente negativo....      
                posx = (int) (45 + (randomGenerator.nextDouble() * (12 * hlimite)));
                posy = (int) (30 + (randomGenerator.nextDouble() * (12 * hlimite)));
            }

            String linea = tmphora + "," + posx + "," + posy + "," + npaquete + "," + idcliente + "," + hlimite + "\r\n";
           // System.out.print(linea);
            escribir.write(linea);
        }
    }

    private static String calchorapedido(int turno, float tiempo) {
        // llega 00:00 (base) y se le suma tiempo en hora
        int nhor = 0;
        int nmin = 0;
        nhor = (turno - 1) * 8;
        int totalmin = 0;

        totalmin = 60 * nhor + nmin;

        totalmin += tiempo;

        Calendar fecha = Calendar.getInstance();
        fecha.set(2013, 5, 21, 00, 00);
        fecha.add(Calendar.MINUTE, totalmin);

        String hora = String.valueOf(fecha.get(Calendar.HOUR_OF_DAY));
        if (hora.length() < 2) {
            hora = "0" + hora;
        }
        String minutos = String.valueOf(fecha.get(Calendar.MINUTE));
        if (minutos.length() < 2) {
            minutos = "0" + minutos;
        }

        String horario = hora + ":" + minutos;
        return horario;
    }

    private static int itemmaximo(int[] numero) {
        // devuelve la posición de mayor valor
        int itemp, imax;
        int i;
        // comienza en 0 como si fuera array
        itemp = 5;  // señal de error
        imax = 0;
        for (i = 0; i < 4; i++) {
            if (imax <= numero[i]) {
                itemp = i;
                imax = numero[i];
            }
        }
        return itemp;
    }
}
